import type { Ref, VNode, UnwrapNestedRefs } from "vue";

export type ComponentType = "input" | "select";
interface renderParams {
  state: {
    [k in string]: any;
  };
  key: string;
  props?: null | any;
  placeholder: string;
  emit: (k: string, payload?: any) => void;
  width?: string;
}
interface renderTableParams {
  column: {
    dataIndex: string;
    slotName: string;
    title: string;
  };
  record: {
    [k in string]: any;
  };
}
interface PageConfig {
  size: number;
  current: number;
  total: number;
}
interface PaginationConfig {
  align: "left" | "center" | "right";
}
type ComponentRender = {
  filter?: (item: renderTableParams) => VNode;
  create?: (item: renderParams) => VNode;
  update?: (item: renderParams) => VNode;
  detail?: (item: renderParams) => VNode;
  query?: (item: renderParams) => VNode;
};
type SearchHandler = () => void;
type ResetHandler = () => void;
type BeforeUpdate = () => void;
type BeforeCreate = () => void;
type BeforeDelete = () => void;
type TableDataProcess = (
  res: any,
  tableData: Ref<never[]>,
  page: PageConfig
) => void;
/**
 * 校验规则
 */
type Rule = {
  type?:
    | "string"
    | "number"
    | "boolean"
    | "array"
    | "object"
    | "email"
    | "url"
    | "ip";
  required?: boolean;
  message?: string;
  length?: number;
  maxLength?: number;
  minLength?: number;
  match?: RegExp;
  uppercase?: boolean;
  lowercase?: boolean;
  min?: number;
  max?: number;
  equal?: number;
  positive?: boolean;
  negative?: boolean;
  true?: boolean;
  false?: boolean;
  includes?: any[];
  deepEqual?: any;
  empty?: boolean;
  hasKeys?: string[];
  validator?: (
    value: any | undefined,
    callback: (error?: string) => void
  ) => void;
};
interface ActionConfig {
  doDetail: (row: any) => void;
  doUpdate: (row: any) => void;
  doDelete: (row: any) => void;
}
interface ComponentAction {
  create?: (doCreate: () => void) => VNode;
  detail?: (row: any, config: ActionConfig) => VNode;
  update?: (row: any, config: ActionConfig) => VNode;
  delete?: (row: any, config: ActionConfig) => VNode;
}
/**
 * create: 在新增中可见;
 * update: 在更新中可见;
 * filter: 在分页中可见;
 * query: 在分页查询条件中可见;
 * detail: 在详情中可见;
 */
interface ComponentVisible {
  create?: boolean;
  update?: boolean;
  filter?: boolean;
  query?: boolean;
  detail?: boolean;
}
export type EditMode = "create" | "update" | "detail";

export interface SubmitConfig {
  emit: any;
  visible: Ref<boolean>;
  models: Template[];
  currMode: EditMode;
  api: string;
  baseUrl: string;
  callback: () => void;
}
export interface Template {
  field: string;
  title: string;
  align?: "left" | "center" | "right";
  placeholder?: string;
  type?: ComponentType;
  props?: {
    [k in string]: any;
  };
  renderItem?: null | ComponentRender;
  visible?: ComponentVisible;
  rules?: Rule[];
}
export interface ModuleConfig {
  title?: string;
  api?: string;
  layout?: "inline" | "horizontal" | "vertical";
}
export interface Templates {
  baseUrl: string;
  api: string;
  models: Template[];
  actions?: null | ComponentAction;
  create?: ModuleConfig;
  update?: ModuleConfig;
  filter?: ModuleConfig;
  detail?: ModuleConfig;
  tableDataProcess?: TableDataProcess;
  pagination?: PaginationConfig;
  onSearch?: null | SearchHandler;
  onReset?: null | ResetHandler;
  onCreate?: null | any;
  onUpdate?: null | any;
  onGetDetail?: any;
  onBeforeCreate?: null | BeforeCreate;
  onBeforeUpdate?: null | BeforeUpdate;
  onBeforeDeleter?: null | BeforeDelete;
}

/**
 * 字典对象
 */
export type Dict = {
  // 展示值
  label: string;
  // 上报值
  value: string;
};

/**
 * 字典依赖
 */
export type DictDependency = Array<{
  name: string;
  fallback: () => Dict[];
}>;

export interface DictLoader<T> {
  onLoad(): Promise<T[]>;

  onMapping(data: T[]): UnwrapNestedRefs<Dict[]>;
}

export type DictInjectOptions = {
  refresh?: number;
};

export type DictCache<T> = {
  data: UnwrapNestedRefs<Dict[]>;
  loader: DictLoader<T>;
  interval: number;
  createAt: number;
};

export type DictContainer<T extends { [K: string]: DictCache<T[keyof T]> }> = {
  [K in keyof T]: K extends string ? DictCache<T[K]> : never;
};

export interface DictManager {
  _container: any;

  /**
   * 注入数据至字典管理器
   * @param key
   * @param loader
   * @param options
   */
  inject<T>(
    key: string,
    loader: DictLoader<T>,
    options?: DictInjectOptions
  ): DictManager;

  map(key: string): any;

  /**
   * 抽取成数组
   * @param key
   * @param condition
   */
  extract(key: string, condition?: (it: Dict) => boolean): Ref<Dict[]>;

  /**
   * 重构结构
   */
  refactor(): void;

  /**
   *
   * @param key
   */
  reload(key: string): void;
}
